package com.easy.secret.interceptor;

import java.util.Map;
import java.util.Objects;
import java.util.Properties;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import com.easy.secret.annotation.SecureData;
import com.easy.secret.service.SecureService;

import lombok.extern.slf4j.Slf4j;

/**
 * @ProjectName: esay-secret-server
 * @Package: com.easy.secret.interceptor
 * @ClassName: EncryptInterceptor
 * @Description: mybatis的加密拦截器
 * @Author: wangjc
 * @CreateDate: 2023/11/17
 * @UpdateUser: wangjc
 * @UpdateDate: 2023/11/17
 * @UpdateRemark: 更新内容
 * @Version: 1.0
 */
@Slf4j
@Component
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class EncryptInterceptor implements Interceptor {
    @Autowired
    private SecureService secureService;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        log.debug("------into encrypt interceptor------");
        MappedStatement mappedStatement  = (MappedStatement) invocation.getArgs()[0];
        String sqlId = mappedStatement.getId();
        log.debug("------sqlId : {}", sqlId);
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        log.debug("------sqlCommandType : {}", sqlCommandType);
        Object paramObj = invocation.getArgs()[1];

        if (Objects.isNull(paramObj)) {
            return invocation.proceed();
        }

        /**
         * 新增
         */
        if (SqlCommandType.INSERT == sqlCommandType) {
            secureEntityObj(invocation.getArgs()[1]);
        }

        /**
         * 修改
         */
        if (SqlCommandType.UPDATE == sqlCommandType && paramObj instanceof Map) {
            Map paramMap = (Map) paramObj;

            // 如果有参数 则调用加解密
            if(Objects.nonNull(paramMap) && paramMap.size() > 0) {
                if(paramMap.containsKey("et")){
                    secureEntityObj(paramMap.get("et"));
                } else if(paramMap.containsKey("param1")) {
                    secureEntityObj(paramMap.get("param1"));
                } else {
                    log.error("Error : 没有et和param1的参数 [ {} ]", paramMap.keySet().toString());
                }
            }
        }

        return invocation.proceed();
    }

    private void secureEntityObj(Object paramObj) {
        SecureData secureData = AnnotationUtils.findAnnotation(paramObj.getClass(), SecureData.class);
        if (Objects.nonNull(secureData)) {
            try {
                secureService.encrypt(paramObj);
            } catch (Exception e) {
                log.error("加密实体对象异常: {}", e);
            }
        }
    }


    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
    }
}
